package fmi.chesstern.ui;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import fmi.chesstern.interpreter.ParseObject.Action;
import fmi.chesstern.interpreter.Parser;


import fmi.chesstern.controller.GameCommandExecutor;
import fmi.chesstern.controller.GameCommandParameters;
import fmi.chesstern.controller.GameCommandType;
import fmi.chesstern.game.BoardField;
import fmi.chesstern.game.GameBoardState;
import fmi.chesstern.game.GameState;
import fmi.chesstern.game.Move;
import fmi.chesstern.interpreter.ParseObject;
import fmi.chesstern.pieces.ChessPiece;
import fmi.chesstern.pieces.ChessPieceColor;
import fmi.chesstern.pieces.ChessPieceType;

public class ConsoleUI implements GameUI {
	
	private boolean running = true;

	public void start(GameCommandExecutor commandExecutor, GameState state) {
		print(state);
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String command;
		while (running) {
			try {
				command = br.readLine();
				ParseObject parseObject = Parser.parseCommand(command);
				executeParseObject(parseObject, commandExecutor, state);
			} catch (IOException e) {
				System.out.println("Incorrect input");
			}
		}
	}
	
	private void executeParseObject(ParseObject parseObject,GameCommandExecutor commandExecutor, GameState state) {
		if (parseObject == null || parseObject.getAction() == Action.UNKNOWN) {
			System.out.println("unknown command");
		} else if (parseObject.getAction() == Action.UNDO) {
			if (state.canUndoMove()) {
				commandExecutor.executeCommand(GameCommandType.UNDO, null);
				System.out.println("undo move");
				print(state);
			} else {
				System.out.println("cannot undo move");
			}
		} else if (parseObject.getAction() == Action.FORFEIT) {
			System.out.println("Game Over");
			commandExecutor.executeCommand(GameCommandType.EXIT, null);
			exit();
		} else if (parseObject.getAction() == Action.MOVE) {
			BoardField start = extractBoardField(parseObject.getParameters().get(0));
			BoardField goal  = extractBoardField(parseObject.getParameters().get(1));
			if (move(new Move(start, goal), commandExecutor, state)) {
				print(state);
				if (state.getGameBoardState().isInMate()) {
					System.out.println("Chessmate!");
				}
			}
		}
		
	}
	
	private BoardField extractBoardField(Object object) {
		char letter = ((String)object).charAt(0);
		int rowIndex = Integer.parseInt((((String)object).substring(1)));
		int colIndex = 0;
		switch (letter) {
		case 'a': colIndex = 0; break;
		case 'b': colIndex = 1; break;
		case 'c': colIndex = 2; break;
		case 'd': colIndex = 3; break;
		case 'e': colIndex = 4; break;
		case 'f': colIndex = 5; break;
		case 'g': colIndex = 6; break;
		case 'h': colIndex = 7; break;
		}
		return new BoardField(rowIndex, colIndex);
	}

	public void exit() {
		running = false;
	}

	private boolean move(Move move, GameCommandExecutor commandExecutor, GameState state) {
		boolean success = false;
		if (state.getGameBoardState().isMoveValid(move)) {
			GameCommandParameters params = new GameCommandParameters();
			params.setParameter("move", move);
			commandExecutor.executeCommand(GameCommandType.MOVE, params);
			System.out.println("successfully moved from " + move.getFrom() + " to " + move.getTo());
			success = true;
		} else {
			System.out.println("Illegal move");
		}
		return success;
	}
	
	
	private void print(GameState state) {
		String printString = "";
		GameBoardState gameState = state.getGameBoardState();
		ChessPiece currentPiece = null;
		System.out.println("   a b c d e f g h ");
		System.out.println("---------------------");
		
		for (int i = 0; i < 8; i++) {
			for (int j = 0; j < 10; j++) {
				if (j == 0) {
					printString = i + "| ";
				} else if (j == 9) {
					printString = "|" + i;
				} else {
					currentPiece = gameState.getPieceAt(new BoardField(i, j - 1));
					if (currentPiece == null) {
						printString = "0 ";
					} else {
						ChessPieceType type = currentPiece.getType();
						switch (type) {
						case PAWN: printString = "p "; break;
						case ROOK: printString = "r "; break;
						case KING: printString = "k "; break;
						case QUEEN: printString = "q "; break;
						case BISHOP: printString = "b "; break;
						case KNIGHT: printString = "h "; break;
						}
						if (currentPiece.getColor() == ChessPieceColor.BLACK) {
							printString = printString.toUpperCase();
						}
					}
				}
				System.out.print(printString);
			}
			System.out.println();
		}
		System.out.println("---------------------");
		System.out.println("   a b c d e f g h ");
	}
	

}
